package com.xf.common.security.starter.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.xf.common.core.authe.feign.UserConsumer;
import com.xf.common.core.domain.DmpResult;
import com.xf.common.core.entity.FebsAuthUser;
import com.xf.common.core.entity.dmp.DmpAuthResourceRole;
import com.xf.common.core.entity.system.SystemUser;
import com.xf.common.core.utils.SecurityUtils;
import com.xf.common.security.starter.service.RbacService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author JoeyLiu
 * @create 2022-04-20 15:42
 */
@Slf4j
@Component("rbacService")
@RequiredArgsConstructor
public class RbacServiceImpl implements RbacService {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    private final UserConsumer userManager;


    /**
     * 获取访问url需要的权限
     *
     * @param url
     * @return 角色
     */
    private List<String> getUrlRoles(String url) {
        Set<String> roles = new HashSet<>();
        DmpResult<List<DmpAuthResourceRole>> result = userManager.getAllResourceRole();
        Map<String, List<String>> rolesMap = result.getData().stream().collect(Collectors.groupingBy(DmpAuthResourceRole::getUrl,
                Collectors.mapping(DmpAuthResourceRole::getRoleName, Collectors.toList())));
        for (Map.Entry<String, List<String>> entry : rolesMap.entrySet()) {
            if (antPathMatcher.match(entry.getKey(), url)) {
                roles.addAll(entry.getValue());
            }
        }
        return new ArrayList<>(roles);
    }

    /**
     * 获取用户角色
     *
     * @param userName
     * @return
     */
    private List<String> getUserRoles(String userName) {
        DmpResult<SystemUser> dmpResult = userManager.findByName(userName);
        if (dmpResult == null || dmpResult.getData() == null) {
            return new ArrayList<>();
        }
        SystemUser systemUser = dmpResult.getData();
        return systemUser.getRoleList();
    }


    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        log.info("请求uri:{}", request.getRequestURI());
        boolean hasPermission = false;
        if (!(authentication instanceof AnonymousAuthenticationToken)) {
            //超级管理员admin不需鉴权
            if (SecurityUtils.getUser(authentication).getIsAdmin()) {
                return true;
            }
            FebsAuthUser authUser = SecurityUtils.getUser(authentication);
            List<String> getUserRoles = getUserRoles(authUser.getUsername());
            if (CollectionUtils.isEmpty(getUserRoles)) {
                return false;
            }
            List<String> needRoles = getUrlRoles(request.getRequestURI());
            for (String needRole : needRoles) {
                //  遍历当前用户所具有的角色
                if (getUserRoles.stream().anyMatch(authority -> authority.equals(needRole))) {
                    hasPermission = true;
                    break;
                }
            }
        }
        return hasPermission;
    }
}
